import { ConfigEnv, loadEnv, PluginOption, UserConfigExport } from 'vite'
import vue from '@vitejs/plugin-vue'
import path, { resolve } from 'path'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import vueJsx from '@vitejs/plugin-vue-jsx'
import Components from 'unplugin-vue-components/vite'
import eslintPlugin from 'vite-plugin-eslint'
import { visualizer } from 'rollup-plugin-visualizer'
import Inspect from 'vite-plugin-inspect'
import { viteMockServe } from 'vite-plugin-mock'
import dts from 'vite-plugin-dts'
import rollupDelete from 'rollup-plugin-delete'
import { viteStaticCopy } from 'vite-plugin-static-copy'
import removeConsole from 'vite-plugin-remove-console'

function _resolve(dir: string) {
  return path.resolve(__dirname, dir)
}

/**
 * val值是否为字符串'true'
 *
 * @param   {string}  val  [val description]
 *
 * @return  {[type]}       [return description]
 */
function envStrValIsTrue(val: string | undefined | null) {
  return val === 'true'
}

export default ({ command, mode }: ConfigEnv): UserConfigExport => {
  const root = process.cwd()
  // 读取.env中配置的环境变量
  const env = loadEnv(mode, root)
  console.log(
    '执行命令: ',
    command,
    ', mode:',
    mode,
    ', env配置文件数据: ',
    env
  )

  // 其他可选插件
  const otherPlugins: (PluginOption | PluginOption[])[] = []
  // 是否进行包分析
  if (envStrValIsTrue(env.VITE_PACKAGE_ANALYZER)) {
    // 启用包分析
    otherPlugins.push(
      visualizer({
        filename: './node_modules/.cache/visualizer/stats.html',
        open: true,
        gzipSize: true,
        brotliSize: true,
      })
    )
  }
  if (command === 'serve' || mode === 'development') {
    otherPlugins.push(Inspect())
    otherPlugins.push(
      viteMockServe({
        // default
        mockPath: 'mock',
        localEnabled: true,
      })
    )
  } else {
    otherPlugins.push(removeConsole())
  }
  const resultConfig: UserConfigExport = {
    plugins: [
      vue(),
      vueJsx(),
      createSvgIconsPlugin({
        // 指定需要缓存的图标文件夹
        iconDirs: [path.resolve(process.cwd(), 'src/assets/svg')],
        // 指定symbolId格式
        symbolId: 'icon-[dir]-[name]',
      }),
      eslintPlugin({
        include: [
          'src/**/*.ts',
          'src/**/*.vue',
          'src/*.ts',
          'src/*.vue',
          'src/*.js',
          'src/**/*.jsx',
          'src/**/*.txs',
          'src/*.jsx',
          'src/*.tsx',
        ],
        cache: false,
      }),
      Components({
        dts: './src/components.d.ts',
      }),
      // 用于生成类型声明文件
      dts({
        outputDir: 'dist', // 指定生成的.d.ts文件的输出目录
        include: './lib', // 指定扫描的目录. 如果不指定，则扫描的整个项目, 因为我们的组件代码是写在lib目录的，所以这里只要指定lib即可
        staticImport: true,
        insertTypesEntry: true,
      }),
      /*
      该组件用于删除一些不必要的资源文件. 
      比如：public文件夹的内容不会直接放入最终的打包目录，里面的文件可能是我们不需要的，因此可以使用这个组件来删除
       */
      rollupDelete({
        targets: ['dist/*.{icon,txt,svg}'],
        hook: 'generateBundle',
      }),
      // 用于直接复制一些文件. 如: 默认只会将scss文件编译成css文件到结果目录，如果希望直接提供scss文件给人使用，那么就需要用到这个复制插件
      viteStaticCopy({
        targets: [
          {
            // 这里表示复制项目根目录下的lib文件夹下的scss文件夹
            src: 'lib/scss',
            // 将src指定的内容，复制到指定目录. 这里设置为空，则会放到项目根目录下的dist目录
            dest: '',
          },
        ],
      }),
      ...otherPlugins,
    ],
    server: {
      host: '0.0.0.0',
      // port: 4200,
      // open: true,
      // proxy: {
      //   '/api': {
      //     target: 'http://jsonplaceholder.typicode.com',
      //     changeOrigin: true,
      //     rewrite: path => path.replace(/^\/api/, ''),
      //   },
      // },
    },
    resolve: {
      alias: {
        '@': _resolve('src'),
        lib: _resolve('lib'),
      },
    },
    build: {
      // minify: false, // 默认true. 如果想看打包之后的文件内容，可以设置为false
      // sourcemap: true, // 默认false. 设置为true则会生成sourcemap文件, sourcemap文件是用于调试源代码的
      lib: {
        entry: resolve(__dirname, 'lib/index.ts'),
        // 对外暴露的组件名
        name: 'YalcClean',
        /**
         * 生成打包结果的文件名. 如配置为: my-button
         * 则会生成如下文件
         * my-button.js:          符合ES规范的打包结果
         * my-button.umd.js       符合UMD规范的打包结果
         * style.css              所有用到的样式都会抽取到这一个样式文件中
         *
         * 因为配置了vite-plugin-dts插件，因此还会生成d.ts的类型声明文件
         * index.d.ts             这个相当于当前组件所有类型声明文件的入口文件, 当前组件的所有类型文件都会从这个引入然后导出
         * MyButton.vue.d.ts      这个是MyButton.vue组件的类型声明文件
         */
        fileName: 'yalc-clean',
      },
      rollupOptions: {
        // 确保外部化处理那些你不想打包进库的依赖
        external: ['fs', 'commander', 'shelljs', 'path', 'rimraf'],
        output: {
          banner: '#!/usr/bin/env node',
          // 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
          globals: {
            fs: 'fs',
            commander: 'commander',
            shelljs: 'shelljs',
            path: 'path',
            rimraf: 'rimraf',
          },
        },
      },
    },
  }
  return resultConfig
}
